Namespace.Use("Application.Sensor.Adapter.Accelerometer", function(ns) {
    //
    //  Imports.
    //
    var DataSetConfiguration = Namespace.Import("Application.Sensor.DataSet.DataSetConfiguration");
    var Inherit = Namespace.Import("Base.Inherit");
    var BaseAdapter = Namespace.Import("Application.Sensor.Adapter.BaseAdapter");
    var QueryParameter = Namespace.Import("Application.Sensor.Query.QueryParameter");

    //
    //  Classes.
    //
    var ADXL335Adapter = Polymorphic.Create(
        [
            String,
            String, String, String, String,
            Boolean,
            String,
            Number, Number, Number,
            Number, Number
        ],
        function(
            name,
            color_x, color_y, color_z, color_combined,
            combined,
            device_id,
            route_x, route_y, route_z,
            min_gravity, max_gravity
        ) {
            //  Let parent class initialize.
            BaseAdapter.call(this);

            //
            //  Members.
            //
            var dataset_x = new DataSetConfiguration(name + "(X)", color_x, min_gravity, max_gravity);
            var dataset_y = new DataSetConfiguration(name + "(Y)", color_y, min_gravity, max_gravity);
            var dataset_z = new DataSetConfiguration(name + "(Z)", color_z, min_gravity, max_gravity);
            var dataset_combined = new DataSetConfiguration(name, color_combined, min_gravity, max_gravity);
            var query = new QueryParameter(device_id, [route_x, route_y, route_z]);

            //
            //  Public methods.
            //
            this.ReceiveData = Polymorphic.Create(
                [String, Array, Array, Number],
                function(rcv_device_id, rcv_routes, rcv_values, rcv_timestamp) {
                    //  Check input data.
                    if (rcv_routes.length != rcv_values.length) {
                        throw "Corrupted data.";
                    }

                    //  Check the device ID.
                    if (rcv_device_id != device_id) {
                        return;
                    }

                    //  Fetch values.
                    var value_x = null, value_y = null, value_z = null;
                    for (var idx = 0; idx < rcv_routes.length; ++idx) {
                        if (rcv_routes[idx] == route_x) {
                            value_x = (rcv_values[idx] - 337.9195) / 67.5839;
                        } else if (rcv_routes[idx] == route_y) {
                            value_y = (rcv_values[idx] - 337.9195) / 67.5839;
                        } else if (rcv_routes[idx] == route_z) {
                            value_z = (rcv_values[idx] - 337.9195) / 67.5839;
                        } else {
                            //  Dummy.
                        }
                    }
                    if (value_x === null || value_y === null || value_z === null) {
                        return;
                    }

                    //  Notify.
                    if (combined == true) {
                        var value_combined = Math.sqrt(value_x * value_x + value_y * value_y + value_z * value_z);
                        if (value_z < 0) {
                            value_combined = -value_combined;
                        }
                        this.TriggerDataCallback({
                            "Values": [
                                value_combined
                            ],
                            "Time": rcv_timestamp
                        });
                    } else {
                        this.TriggerDataCallback({
                            "Values": [
                                value_x,
                                value_y,
                                value_z
                            ],
                            "Time": rcv_timestamp
                        });
                    }
                }
            );
            this.GetDataSets = function() {
                if (combined == true) {
                    return [
                        dataset_combined
                    ];
                } else {
                    return [
                        dataset_x,
                        dataset_y,
                        dataset_z
                    ];
                }
            };
            this.GetQueryParameter = function() {
                return query;
            };
        }
    );

    //  Inherit "ADXL335Adapter" from "BaseAdapter".
    Inherit(ADXL335Adapter, BaseAdapter);

    //  Export public APIs / classes.
    Namespace.Export(ns, "ADXL335Adapter", ADXL335Adapter);
});
